// http://stackoverflow.com/questions/8588563/adding-custom-properties-to-a-function

//ver 1
if(false){
    var keyValueStore = (function() {
        return {
            'data' : {},
            'get' : function(key) { return keyValueStore.data[key]; },
            'set' : function(key, value) { keyValueStore.data[key] = value; },
            'delete' : function(key) { delete keyValueStore.data[key]; },
            'getLength' : function() {
                var l = 0;
                for (p in keyValueStore.data) l++;
                return l;
            }
        }
    })();

    // test
    keyValueStore.set('a','b');
    keyValueStore.set('c','d');
    console.log(keyValueStore.get('a'));
    console.log(keyValueStore.getLength());
    keyValueStore.delete('a');
    console.log(keyValueStore.getLength());
}

//ver 2 make the 'data' variable private
if(false){
    var keyValueStore = (function() {
        var data = {};
        return {
            'get' : function(key) { return keyValueStore.data[key]; },
            'set' : function(key, value) { keyValueStore.data[key] = value; },
            'delete' : function(key) { delete keyValueStore.data[key]; },
            'getLength' : function() {
                var l = 0;
                for (p in keyValueStore.data) l++;
                return l;
            }
        }
    })();
}


//ver 3 factory mode
if(false){
    var keyValueStore = (function() {
        var count = -1;
        return (function kvs() {
            count++; 
            return {
                'data' : {},
                'create' : function() { return new kvs(); },
                'count' : function() { return count; },
                'get' : function(key) { return this.data[key]; },
                'set' : function(key, value) { this.data[key] = value; },
                'delete' : function(key) { delete this.data[key]; },
                'getLength' : function() {
                    var l = 0;
                    for (p in this.data) l++;
                    return l;
                }
            }
        })();
    })();
    
    // test
    var kvpari1 = keyValueStore.create();
    kvpari1.set('a','b');
    console.log(kvpari1.get('a'));

    var kvpari2 = keyValueStore.create();
    kvpari2.set('a','c');
    console.log(kvpari2.get('a'));

    console.log(kvpari2.count());
}


// ver 4 this should be good
if(true){
    var keyValueStore = (function() {
        var count = 0; // Singleton private properties
        var kvs = function() {
            count++; // Instance private properties
        };

        kvs.prototype = { // Instance public properties
            'data' : {},
            'get' : function(key) { return this.data[key]; },
            'set' : function(key, value) { this.data[key] = value; },
            'delete' : function(key) { delete this.data[key]; },
            'getLength' : function() {
                var l = 0;
                for (p in this.data) l++;
                return l;
            }
        };

        return  { // Singleton public properties
            'create' : function() { return new kvs(); },
            'count' : function() { return count; }
        };
    })();

    // test
    var kvpari1 = keyValueStore.create();
    kvpari1.set('a','b');
    console.log(kvpari1.get('a'));

    var kvpari2 = keyValueStore.create();
    kvpari2.set('a','c');
    console.log(kvpari2.get('a'));

    console.log(keyValueStore.count());
}